import backtrader as bt
import numpy as np
import pandas as pd
import traceback
import datetime
from indicators.KeyPointsInd import KeyPointsInd
from indicators.wave_index_ind import wave_index_ind
import pymysql

class nowMysqlTimeBehindtrategy(bt.Strategy):
    # 策略参数
    params = dict(
        period=20,  # 均线周期
        look_back_days=30,
        printlog=False,
        period_ema_fast=10,
        period_ema_slow=100,
        short_window=20,
        long_window=60,
        N1=3,
        N2=50,
        N3=25,
        key_window=25,
        wave_two_window=50,
        wave_three_window=70,
        distance=20,
        prominence=3
    )
    def __init__(self):
        try:
         for data in self.datas:
           data.stockdata = KeyPointsInd().getwave(distance=self.p.distance,prominence=self.p.prominence, data=data,show=False,ago=None,size=None)
           data.resistance_val=0
           data.resistance_val_list=[]
           data.resistance_buy = 0  # 突破买入点
           data.resistance_sell = 0  # 跌破卖出点
           data.profit_sell = 0#盈利卖出
           data.resistance_val = 0# 阻力点
           data.resistance_len =0 # 阻力点发生的位置
           data.resistance_h_and_l=0#高点地点相加作为标识符使用
           data.short_ma = bt.indicators.SMA(data.close, period=self.p.short_window)
           data.profit = 0
           data.resistance_h=0#阻力
           data.resistance_h_ind=0
           data.resistance_bili = 0#最小比例值

           data.resistance_sell_order=0#已生成订单的止损点
           data.profit_sell_order = 0  # 已生成订单的盈利卖出

           data.profit_h_order = 0  # 订单中的高点
           data.order_price=0#订单买入价

           data.getKeyPoint = False#是否获得关键点
           data.getKeyPointLen=0#已获得的关键点位置
           data.getKeyPointH = 0  # 是否获得关键点
           data.getKeyPointL= 0  # 是否获得关键点



           #for A, B in zip(stockdata['val'], stockdata['ind']):
           #    print(A, B)
           #print(KeyPointsInd)



        except Exception as e:
            traceback.print_exc()

        #遍历所有股票,计算20日均线
        #for data in self.datas:

    def notify_order(self, order):
        """
        订单状态处理

        Arguments:
            order {object} -- 订单状态
        """
        if order.status in [order.Submitted, order.Accepted]:
            # 如订单已被处理，则不用做任何事情
            return

        # 检查订单是否完成
        if order.status in [order.Completed]:
            if order.isbuy():
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
                #print('BUY成交, 执行价={0}, {1}'.format(order.executed.price, order.executed.size))
            #elif order.issell():
                #print('SELL成交, 执行价={0}, {1}'.format(order.executed.price, order.executed.size))
            self.bar_executed = len(self)
        # 订单因为缺少资金之类的原因被拒绝执行
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
        # 订单状态处理完成，设为空
        self.order = None

    def notify_trade(self, trade):
        """
        交易成果

        Arguments:
            trade {object} -- 交易状态
        """
        if not trade.isclosed:
            return

        # 显示交易的毛利率和净利润
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm), doprint=True)

    def next(self):
        total_value = self.broker.getvalue()
        p_value = total_value*0.9/10
        for data in self.datas:
         # print(len(data))
         if len(data) == (data.buflen()):
              stockdata=data.stockdata
              h = self.getKeyNum(stockdata, len(data), 1)  # 前高点

              if h == None:
                 return

          #if h is not None :
            #print(h.time.date())
          #datetimeNum = h.ind * -1
          #最后一天

              # print(data.buflen())
              # print(h.ind)
              lastData = KeyPointsInd().getwave(distance=None, prominence=None, data=data, show=False, ago=0,size=data.buflen() - int(h.ind))
              for row in lastData.itertuples():
                  ind = row.ind
                  type = row.type
                  if type == 1 :#是否高点
                      #distance = h.ind - ind# 与最高点之间距离
                      z_distance =  h.ind+ (ind*3)
                      if len(data)>=z_distance and len(data) <(z_distance+ind):#三到四之间
                          minData = lastData['val'].min()
                          plan = (h.val-minData)*0.23+minData
                          plan_h = (h.val - minData) * 0.35 + minData
                          if data.close[0] > plan and data.close[0]<plan_h:
                              #print(h.time.date())
                              db = pymysql.connect(host='101.35.200.120', port=3306, user='root', passwd='ljf123456',db='gp', charset='utf8')
                              # 使用cursor()方法获取操作游标
                              cursor = db.cursor()
                              date_p = datetime.datetime.now().date()
                              str_p = str(date_p)
                              selectSql = """select * from record_strategy  WHERE  code = '%s'  AND strateg_type = %s """ \
                                          % (data._name, 1)
                              cursor.execute(selectSql)
                              # print(selectSql)
                              selectResults = cursor.fetchall()
                              if (len(selectResults) == 0):
                                  #datetime.datetime.now().year + '-' + datetime.datetime.now().month + '-' + datetime.datetime.now().day
                                  #time =date_p = datetime.datetime.now().date()
                                  sql1 = """INSERT INTO record_strategy (code,strateg_type,is_permanent,create_time) VALUES ('%s','%s','%s','%s') """ \
                                         % (data._name,1,0,str_p)
                                  cursor.execute(sql1)
                                  id=cursor.lastrowid
                                  sql1 = """INSERT INTO record_strategy_price (strategy_id,max_price,min_price,resistance_price) VALUES ('%s','%s','%s','%s') """ \
                                         % (id, h.val, minData, plan)
                                  cursor.execute(sql1)
                                  #print(id)
                              # 执行sql语句
                              db.commit()
                              #print ( '代码:', data._name, '阻力位:', plan, '高点:',h.val, '低点:', minData, '总距离：', z_distance )
    def log(self, txt, dt=None,doprint=False):
        if self.params.printlog or doprint:
            dt = dt or self.datas[0].datetime.date(0)
            print(f'{dt.isoformat()},{txt}')

    #  or self.getFrontB( data, 3) == True


    def getFrontB(self, data,  end):
        for i in range(1, end):
            if data.close[-i] > data.close[-(i+1)]:
                return False
        return True

    #冒泡查询
    def getKeyNum(self, stockdata, indNum,dataType):
        data=None
        for row in stockdata.itertuples():
            ind = row.ind
            type =row.type
            if type == dataType and indNum > ind :
                data = row
                break
        return data

    #
    def getResistance_sell_order(self, data):
        bili = data.resistance_bili
        close= data.close[0]
        low= data.low[0]
        resistance_val=data.resistance_val
        for i in range(1, 20):
            d = resistance_val+(resistance_val*bili*i)
            if low > d:
                data.resistance_sell_order = d*0.8  # 已生成订单的止损点

    #获取
    def getKeyPoint(self, data):
        if data.getKeyPoint==True:
           return
        stockdata = data.stockdata
        h = self.getKeyNum(stockdata, len(data), 1)  # 前高点
        if h is not None :
            l = self.getKeyNum(stockdata, h.ind, 2)  # 前高点
            if l is not None:
                resistance = (h.val - l.val) / l.val
                bili = int(resistance + 1) * 2
                if bili == 0:
                    return
                # 最小分数
                bili = (resistance / bili) / 2
                if bili < 0.1:
                    return
                # resistance_val=h.val -(h.val * bili)
                for i in range(2, 4):
                    resistance_val = h.val - (h.val * bili * i)  # 关键线
                    # 判断阻力线是否已被触及，当前及之前
                    if data.resistance_val == resistance_val or resistance_val in data.resistance_val_list \
                            or ((h.val + l.val) == data.resistance_h_and_l and data.resistance_val < resistance_val):
                        continue
                    if data.high[0] > resistance_val and data.low[0] < resistance_val:
                        data.getKeyPointH=h.val
                        data.getKeyPointL=l.val
                        data.getKeyPoint=True
                        data.resistance_buy = (resistance_val * bili * 0.75) + resistance_val
                        data.resistance_h = data.high[0]
                        data.resistance_h_ind = h.ind
                        data.resistance_bili = bili
                        # data.high[0]#突破买入点
                        data.resistance_sell = resistance_val - (resistance_val * bili)
                        # resistance_val- (resistance_val*bili)
                        # data.low[0]  # 跌破卖出点
                        data.profit_sell = (resistance_val * bili * 2) + resistance_val
                        data.resistance_val = resistance_val  # 写入回测数据众
                        data.resistance_len = len(data)  # 阻力点发生的位置
                        #print('代码:', data._name, '买入位:', data.resistance_buy, '阻力位:', data.resistance_val, '高点:', h.val,
                        #      '低点:', l.val)
                        data.resistance_h_and_l = h.val + l.val  # 阻力数据相加，作为标识符

    #记录交易收益情况（可省略，默认不输出结果）
    #def notify_trade(self,trade):
    #    if not trade.isclosed:
    #        return
    #    self.log(f'策略收益：\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}')
